﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Collections.Specialized;
using ShredTheLog.Model;
using ShredTheLog.Common.MVVM;
using System.Globalization;
using ShredTheLog.Api.DataContracts;
using System.Windows.Threading;
using ShredTheLog.Api;
using System.ComponentModel.Composition;
using ShredTheLog.Views;
using System.Diagnostics;

namespace ShredTheLog.ViewModels
{
    public sealed class HomePageViewModel : ViewModelBase
    {
        [Import]
        private IShredServices ShredServices { get; set; }

        [Import]
        private IConnectionSettingsSection ConnectionSettings { get; set; }

        [Import]
        public IRegisterCommand RegisterCommand { get; private set; }

        [Import]
        public IEditProfileCommand EditProfileCommand { get; private set; }

        [Import]
        public IDiscoverSharedTalkCommand DiscoverSharedTalkCommand { get; private set; }

        [Import]
        public IGoToTextChatCommand GoToTextChatCommand { get; private set; }

        [Import]
        public IGoToContactListCommand GoToContactListCommand { get; private set; }

        [Import]
        public IGoToUserSearchCommand GoToUserSearchCommand { get; private set; }

        [Import]
        public IGoToMailboxCommand GoToMailboxCommand { get; private set; }

        [Import]
        public IGoToVoiceChatCommand GoToVoiceChatCommand { get; private set; }

        public HomePageViewModel()
        {
            VoiceChatUsers = new ReadOnlyObservableCollection<IBasicUserInfo>(_internalVoiceChatUsers);
            TextChatUsers = new ReadOnlyObservableCollection<IShortUserInfo>(_internalTextChatUsers);
            Last15Users = new ReadOnlyObservableCollection<ILast15UserInfo>(_internalLast15Users);
        }

        public ReadOnlyObservableCollection<IContact> Contacts { get { return ShredServices.Contacts; } }

        private ObservableCollection<IBasicUserInfo> _internalVoiceChatUsers = new ObservableCollection<IBasicUserInfo>();
        public ReadOnlyObservableCollection<IBasicUserInfo> VoiceChatUsers { get; private set; }

        private ObservableCollection<IShortUserInfo> _internalTextChatUsers = new ObservableCollection<IShortUserInfo>();
        public ReadOnlyObservableCollection<IShortUserInfo> TextChatUsers { get; private set; }

        private ObservableCollection<ILast15UserInfo> _internalLast15Users = new ObservableCollection<ILast15UserInfo>();
        public ReadOnlyObservableCollection<ILast15UserInfo> Last15Users { get; private set; }

        private bool _isUpdatingUserLists;
        public bool IsUpdatingUserLists 
        { 
            get { return _isUpdatingUserLists; } 
            private set 
            {
                _isUpdatingUserLists = value;
                OnPropertyChanged(() => IsUpdatingUserLists);
            } 
        }

        private ICommand _updateUserListsCommand;
        public ICommand UpdateUserListsCommand
        {
            get
            {
                if (_updateUserListsCommand == null)
                {
                    _updateUserListsCommand = new DelegateCommand(
                        () =>
                        {
                            IsUpdatingUserLists = true;
                            bool isUpdatingVoiceChatUsersList = true;
                            bool isUpdatingTextChatUsersList = true;
                            bool isUpdatingLast15UsersList = true;

                            Action<Exception> onError =
                                ex =>
                                {
                                    Trace.WriteLine(String.Format("{0}: Failed to get list of users.", this.GetType().Name));
                                    Trace.WriteLine(ex.ToString());
                                };
                            ConnectionSettings.GetClient().GetVoiceChatUsers().ObserveOn(ShredServices.Dispatcher).Subscribe(
                                args =>
                                {
                                    try
                                    {
                                        _internalVoiceChatUsers.Merge(args, u => u);
                                        isUpdatingVoiceChatUsersList = false;
                                        if (!isUpdatingVoiceChatUsersList && !isUpdatingTextChatUsersList && !isUpdatingLast15UsersList)
                                            IsUpdatingUserLists = false;
                                    }
                                    catch (Exception ex)
                                    {
                                        onError(ex);
                                    }
                                },
                                onError);

                            ConnectionSettings.GetClient().GetTextChatUsers().ObserveOn(ShredServices.Dispatcher).Subscribe(
                                args =>
                                {
                                    try
                                    {
                                        _internalTextChatUsers.Merge(args, u => u);
                                        isUpdatingTextChatUsersList = false;
                                        if (!isUpdatingVoiceChatUsersList && !isUpdatingTextChatUsersList && !isUpdatingLast15UsersList)
                                            IsUpdatingUserLists = false;
                                    }
                                    catch (Exception ex)
                                    {
                                        onError(ex);
                                    }
                                },
                                onError);

                            ConnectionSettings.GetClient().GetLast15Users().ObserveOn(ShredServices.Dispatcher).Subscribe(
                                args =>
                                {
                                    try
                                    {
                                        _internalLast15Users.Merge(args, u => u);
                                        isUpdatingLast15UsersList = false;
                                        if (!isUpdatingVoiceChatUsersList && !isUpdatingTextChatUsersList && !isUpdatingLast15UsersList)
                                            IsUpdatingUserLists = false;
                                    }
                                    catch (Exception ex)
                                    {
                                        onError(ex);
                                    }
                                },
                                onError);
                        });
                }
                return _updateUserListsCommand;
            }
        }
    }
}
